//	Project:	HexTower
//	File:		Game.cpp
//	Author:		Mustafa Aldoori
//	Purpose:	Implementation on the Game class.

#include "Game.h"
#include "GamePlayState.h"

// Singleton
CGame* CGame::GetInstance( void )
{
	// Lazy Instantiation
	static CGame s_Instance;

	return &s_Instance;
}

CGame::CGame( void )
{
	m_nScreenWidth	= -1;
	m_nScreenHeight = -1;
	m_bWindowed		= true;

	m_dwGameTime = 0;

	m_pD3D = nullptr;
	m_pDI = nullptr;
	m_pGM = nullptr;
}

CGame::~CGame( void )
{

}

void CGame::Initialize( HWND hWnd, HINSTANCE hInstance, int nScreenWidth, int nScreenHeight, bool bWindowed )
{
	SetWindowHandle( hWnd );
	HRGN hrgn = CreateRectRgn( 10, 30, 1280, 830 );
	SetWindowRgn( hWnd, hrgn, TRUE );

	m_pD3D = Direct3D_Manager::GetInstance();
	m_pD3D->InitDirect3D( hWnd, nScreenWidth, nScreenHeight, bWindowed, false );

	m_pDI = DirectInput_Manager::GetInstance();
	m_pDI->InitDirectInput( hWnd, hInstance, DI_KEYBOARD | DI_MOUSE );

	m_pGM = DirectGraphics_Manager::GetInstance();
	m_pGM->InitGraphics_Manager( m_pD3D->GetDirect3DDevice(), m_pD3D->GetSprite() );

	// Store the screen info
	m_nScreenWidth	= nScreenWidth;
	m_nScreenHeight = nScreenHeight;
	m_bWindowed		= bWindowed;

	PushState( CGamePlayState::GetInstance() );

	// Store the current time
	m_dwGameTime = GetTickCount();
}

// Play
bool CGame::Main( void )
{
	if( m_vpStates.size() == 0 )
		return false;

	Input();
	Update();
	Render();

	return true;
}

bool CGame::Input( void )
{
	m_pDI->ReadDevices( );

	return m_vpStates.back()->Input();
}

void CGame::Update( )
{
	DWORD now = GetTickCount();
	float fElapsed = (now - m_dwGameTime) / 1000.0f;
	m_dwGameTime = now;

	if( fElapsed > 0.05f)//0.125f)
		fElapsed = 0.05f;

	m_vpStates.back()->Update( fElapsed );
}

void CGame::Render( void )
{
	m_pD3D->Clear( 0, 0, 0 );

	m_pD3D->DeviceBegin();
	m_pD3D->SpriteBegin();

	m_vpStates.back()->Render();

	m_pD3D->SpriteEnd();
	m_pD3D->DeviceEnd();

	m_pD3D->Present();
}

void CGame::Shutdown( void )
{
	m_vpStates.clear();

	if( m_pDI != nullptr )
	{
		m_pDI->ShutdownDirectInput();
		m_pDI = nullptr;
	}

	if( m_pD3D != nullptr )
	{
		m_pD3D->ShutdownDirect3D();
		m_pD3D = nullptr;
	}

	// Reset the members
	m_nScreenWidth	= -1;
	m_nScreenHeight = -1;
	m_bWindowed		= true;
}

void CGame::FullScreenMode( bool setToFullScreen )
{
	if( this->IsWindowed() == true && setToFullScreen == true )
	{
		m_pD3D->ChangeDisplayParam( this->GetWidth(), this->GetHeight(), false );
		this->m_bWindowed = false;
	}
	else if( this->IsWindowed() == false && setToFullScreen == false )
	{
		m_pD3D->ChangeDisplayParam( this->GetWidth(), this->GetHeight(), true );
		this->m_bWindowed = true;
	}
}

void CGame::PopState( bool bEnterState  )
{
	if( m_vpStates.size() > 0 )
	{
		m_vpStates.back()->Exit();
		m_vpStates.pop_back();
	}

	if( m_vpStates.back() > 0 )
	{
		if( bEnterState == true )
			m_vpStates.back()->Enter();
		else {}
	}
}

void CGame::PushState( IGameState* pNewState, bool bExitState)
{
	if( m_vpStates.size() > 0 )
		if( bExitState == true )
		m_vpStates.back()->Exit();
		else {}

	m_vpStates.push_back( pNewState );

	if( m_vpStates.size() > 0 )
		m_vpStates.back()->Enter();
}